
package com.googlecode.mvndroid.tools;

import com.googlecode.mvndroid.AndroidMojo;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;

/**
 * Abstract android tool.
 *
 * @author <a href="mailto:1.024e3@gmail.com">Bartosz Duzy</a>
 */
public abstract class AndroidTool{

    protected static final int PROCESS_LOOP_SLEEP_MILLIS = 100;
    protected static final int EXIT_SUCCESS = 0;
    protected AndroidMojo context;
    protected InputStream psOut;
    protected InputStream psErr;
    protected List<String> parameters = new ArrayList<String>();
    
    protected AndroidTool(AndroidMojo sharedContext) {
        this.context = sharedContext;
    }

    public void execute() throws MojoExecutionException, MojoFailureException {
        execute(new ProcessBuilder());
    }

    public void execute(ProcessBuilder processBuilder) throws MojoExecutionException, MojoFailureException {

        List<String> commandLine = new ArrayList<String>(getParameters());
        File toolsDir = new File(context.getAndroidToolsDir().getAbsolutePath());
        File tool = new File(toolsDir,getName());

        if(!tool.exists()){
            toolsDir = new File(context.getAndroidToolsPlatformDependentDir().getAbsolutePath());
            tool = new File(toolsDir,getName());
        }
        
        String commandLineString = "Executing command:";
        Log log = context.getLog();
        
        commandLine.addAll(0, Arrays.asList(
                tool.getAbsolutePath()
        ));

        for(String cmd: commandLine)
            commandLineString+=" "+cmd;

        log.debug(commandLineString);

        processBuilder.command(commandLine);

        try {
            int exitValue;
            Process process = processBuilder.start();
            psOut = process.getInputStream();
            psErr = process.getErrorStream();
            BufferedReader outReader = new BufferedReader(new InputStreamReader(psOut));
            do {
                try {
                    exitValue = process.exitValue();
                    break;
                } catch (IllegalThreadStateException e) {
                    Thread.sleep(PROCESS_LOOP_SLEEP_MILLIS);
                } finally {
                    while (outReader.ready()) {
                        log.info(outReader.readLine());
                    }
                }
            } while(true);
            if (exitValue != EXIT_SUCCESS) {
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(psErr));
                while (errorReader.ready()) {
                    log.error(errorReader.readLine());
                }
                String errorMessage = getErrorMessage();
                log.error(errorMessage);
                log.error("For more detail on what might be causing the problem try running maven with the --debug option ");
                throw new MojoFailureException(errorMessage);
            }
        } catch (IOException e) {
            throw new MojoExecutionException(getErrorMessage() + " IOException: " + e.getMessage());
        } catch (InterruptedException e) {
            throw new MojoExecutionException(getErrorMessage() + " Process was interrupted: " + e.getMessage());
        }
    }

    protected abstract String getName();

    public  void setParameters(List<String> parameters) {
        this.parameters=parameters;
    }

    protected List<String> getParameters(){
        return parameters;
    };

    protected abstract String getErrorMessage();

}
